package actors

import java.io.File

import akka.actor.typed.Behavior
import akka.actor.typed.scaladsl.Behaviors
import command.CommandExec
import dao.{MissionDao, ModeDao}
import models.Tables.MissionRow
import org.apache.commons.io.FileUtils
import org.joda.time.DateTime
import tool.Pojo._
import tool.Tool
import utils.Utils
import implicits.Implicits._

import scala.concurrent.ExecutionContext.Implicits.global
import scala.util.{Failure, Success}

/**
 * Created by yz on 13/4/2020
 */
object MissionExecutor {

  sealed trait Message

  case class MissionStart(mission: MissionRow) extends Message

  case class MissionError(myMessage: MyMessage, mission: MissionRow) extends Message

  def runScript(workspaceDir: File, data: MissionData) = {
    val db = data.db
    val reportFile = Tool.getReportFile(workspaceDir)
    val outputFile = Tool.getOutputFile(workspaceDir)
    val fq1File = Tool.getFq1File(workspaceDir)
    val fq2File = Tool.getFq2File(workspaceDir)
    val command =
      s"""
         |centrifuge -q -x ${Tool.indexDir.unixPath}/${db}/${db} -1 ${fq1File.unixPath} -2 ${fq2File.unixPath} --trim5 ${data.trim5} --trim3 ${data.trim3} -p ${data.threadNum} --report-file ${reportFile.unixPath} -S ${outputFile.unixPath}
         |centrifuge-kreport -x ${Tool.indexDir.unixPath}/${db}/${db}  ${outputFile.unixPath} > ${data.missionName}_view.txt
           """.stripMargin
    CommandData(workspaceDir, List(command))
  }

  def missionResultDeal(workspaceDir: File, resultDir: File) = {
    Tool.getReportFile(workspaceDir).fileCopyToDir(resultDir)
    Tool.getOutputFile(workspaceDir).fileCopyToDir(resultDir)
    workspaceDir.myListFiles.filter(_.endsWith("_view.txt")).foreach { x =>
      x.fileCopyToDir(resultDir)
    }
  }

  def apply()(implicit missionDao: MissionDao): Behavior[Message] =
    Behaviors.receive { (context, message) =>
      message match {
        case MissionStart(mission) =>
          val workspaceDir = Tool.getMissionWorkspaceDir(mission)
          val json = Utils.configFile2Json(workspaceDir)
          val data = MyCodec[MissionData].decode(json)
          val logFile = Tool.getInitLogFile(workspaceDir.getParentFile)
          val newMision = mission.copy(state = "running")
          missionDao.update(newMision).map { x =>
            val resultDir = Tool.getMissionResultDir(mission)
            val commandExec = CommandExec().exec { b =>
              runScript(workspaceDir, data)
            }.map { b =>
              missionResultDeal(workspaceDir, resultDir)
            }
            val state = if (commandExec.isSuccess) {
              "success"
            } else {
              commandExec.errorInfo.toFile(logFile)
              "error"
            }
            val newMission = mission.copy(state = state, endTime = Some(new DateTime()))
            missionDao.update(newMission).map { x =>
            }
          }.onComplete {
            case Failure(e) =>
              e.printStackTrace()
              context.self ! MissionError(MyMessage(valid = false, message = e.getMessage), mission)
            case Success(x) =>
          }
          Behaviors.same
        case MissionError(myMessage, mission) =>
          val state = "error"
          val newMission = mission.copy(state = state, endTime = Some(new DateTime()))
          missionDao.update(newMission).map { x =>
            val missionIdDir = Tool.getMissionIdDir(mission)
            val logFile = Tool.getInitLogFile(missionIdDir)
            myMessage.message.toFile(logFile)
          }
          Behaviors.same
      }


    }


}
